package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

/* 使用goroutine和channel实现一个计算int64随机数各位数和的程序。
开启一个goroutine循环生成int64类型的随机数，发送到jobChan
开启24个goroutine从jobChan中取出随机数计算各位数的和，将结果发送到resultChan
主goroutine从resultChan取出结果并打印到终端输出
为了保证业务代码的执行性能将之前写的日志库改写为异步记录日志方式。 */

type job struct {
	sz int64
}

type result struct {
	job    *job
	cx     int
	result int64
}

var jobChan = make(chan *job, 100)
var resultChan = make(chan *result, 100)
var wg sync.WaitGroup

func zhoulin(jobChan chan<- *job) {
	defer wg.Done()
	//开启一个goroutine循环生成int64类型的随机数，发送到jobChan
	for i := 0; i < 10; i++ {
		x := rand.Int63()
		newJob := &job{
			sz: x,
		}
		jobChan <- newJob
		time.Sleep(time.Millisecond * 500)
	}
	close(jobChan)
	close(resultChan) //在这个位置，确实不是很理解
}

func baodelu(i int, jobChan <-chan *job, resultChan chan<- *result) {
	defer wg.Done()
	//开启24个goroutine从jobChan中取出随机数计算各位数的和，将结果发送到resultChan
	for job := range jobChan {
		sum := int64(0)
		n := job.sz
		for n > 0 {
			sum += n % 10
			n = n / 10
		}
		newResult := &result{
			job:    job,
			cx:     i,
			result: sum,
		}
		resultChan <- newResult
	}
}

func main() {
	wg.Add(1)
	go zhoulin(jobChan)
	//开启24个goroutine从jobChan中取出随机数计算各位数的和，将结果发送到resultChan
	wg.Add(4)
	for i := 0; i < 4; i++ {
		go baodelu(i, jobChan, resultChan)
	}
	//主goroutine从resultChan取出结果并打印到终端输出
	for result := range resultChan {
		fmt.Printf("cx:%d  value:%d  sum:%d \n", result.cx, result.job.sz, result.result)
	}

	wg.Wait()
}
